import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';

import { HTTPResult, PageData } from 'src/types/httpResult';

import { localStorage } from 'src/adapter/localstorage';

import userApi from 'src/api/user/index';

import { Notify } from 'quasar';

const instance = axios.create({
  baseURL: process.env.PROD
    ? process.env.PROD_BASE_URL
    : process.env.DEV_BASE_URL
});

let requestQueue: any[] = [];
let isRefreshing = false;

instance.interceptors.request.use((config: AxiosRequestConfig) => {
  let token = localStorage.getItem('ACCESS_TOKEN');
  const { headers } = config;
  if (token) {
    headers['Authorization'] = 'Bearer ' + token;
  }
  return config;
});

instance.interceptors.response.use(
  response => {
    if (response.data.retCode == 401) {
      const config = response.config;
      const refreshToken = localStorage.getItem('REFRESH_TOKEN');
      if (refreshToken) {
        if (!isRefreshing) {
          isRefreshing = true;
        }

        requestQueue = [];
        return userApi
          .refreshToken(refreshToken)
          .then(res => {
            if (res.success) {
              localStorage.setItem('ACCESS_TOKEN', res.data.access_token.token);
              localStorage.setItem(
                'REFRESH_TOKEN',
                res.data.refresh_token.token
              );
              requestQueue.forEach((res: Function) => res());
              requestQueue = [];
              return instance(config);
            }
          })
          .catch(err => {
            console.error('refreshtoken error =>', err);
            return null;
          })
          .finally(() => {
            isRefreshing = false;
          });
      }
    }
    if (!response.data.success) {
      Notify.create({
        message: response.data.msg,
        type: 'negative',
        position: 'top'
      });
      return null;
    }

    return response.data;
    // return response.data.success
    //   ? response.data
    //   : Promise.reject(response.data);
  },
  error => {
    console.log('报错了', error);
    const errorJSON = error.toJSON();
    const messageText = error.response?.data?.message || 'Error';
    const errorText =
      error.response?.data?.error ||
      error.response?.statusText ||
      errorJSON.message;
    const errorInfo = {
      ...errorJSON,
      config: error.config,
      request: error.request,
      response: error.response,
      code: error.code || error.response?.status || 400,
      message: messageText + ': ' + errorText
    };
    console.debug('axios error:', errorInfo.message);
    return Promise.reject(errorInfo);
  }
);

const request = {
  $: instance,
  request: <T = any>(
    ...args: Parameters<AxiosInstance['request']>
  ): Promise<HTTPResult<T>> => instance.request(...args),
  get: <T = any>(
    ...args: Parameters<AxiosInstance['get']>
  ): Promise<HTTPResult<T>> => instance.get(...args),
  fetchList: <T = any>(
    ...args: Parameters<AxiosInstance['get']>
  ): Promise<HTTPResult<T[]>> => instance.get(...args),
  fetchPageList: <T = any>(
    ...args: Parameters<AxiosInstance['get']>
  ): Promise<HTTPResult<PageData>> => instance.get(...args),
  delete: <T = any>(
    ...args: Parameters<AxiosInstance['delete']>
  ): Promise<HTTPResult<T>> => instance.delete(...args),
  head: <T = any>(
    ...args: Parameters<AxiosInstance['head']>
  ): Promise<HTTPResult<T>> => instance.head(...args),
  options: <T = any>(
    ...args: Parameters<AxiosInstance['options']>
  ): Promise<HTTPResult<T>> => instance.options(...args),
  post: <T = any>(
    ...args: Parameters<AxiosInstance['post']>
  ): Promise<HTTPResult<T>> => instance.post(...args),
  put: <T = any>(
    ...args: Parameters<AxiosInstance['put']>
  ): Promise<HTTPResult<T>> => instance.put(...args),
  patch: <T = any>(
    ...args: Parameters<AxiosInstance['patch']>
  ): Promise<HTTPResult<T>> => instance.patch(...args),
  fetch: (url: string): any => fetch(url)
};

export default request;
